import os
import json
import time
from rich.console import Console
from rich.panel import Panel

console = Console()

class GameState:
    def __init__(self):
        self.current_node = ""
        self.data = {}
        self.player_name = "玩家"
        self.character_descriptions = {}

def clear_screen():
    """清屏函数"""
    os.system('cls' if os.name == 'nt' else 'clear')

def typewriter_effect(text, delay=0.03):
    """逐字显示效果"""
    text = text.replace("#%#", "\n")
    for char in text:
        console.print(char, end="", style="cyan", highlight=False)
        time.sleep(delay)
    console.print()
    console.input("[bold magenta]\n=== 按Enter键继续 ===[/bold magenta]")

def display_choices(choices):
    """显示选项面板"""
    console.rule("[yellow]请做出你的选择[/yellow]")
    for idx, (choice, _) in enumerate(choices, 1):
        console.print(f"[bold green][{idx}][/] {choice}")
    console.rule()

def display_text(state):
    """显示剧情文本"""
    current = state.data.get(state.current_node, {})
    
    # 处理说话者信息
    speaker = current.get("speaker", "旁白")
    if speaker == "player":
        speaker = state.player_name
    
    # 显示剧情面板
    console.rule(f"[bold yellow]{current.get('title', '故事进行中')}[/bold yellow]")
    
    # 显示角色信息
    if speaker in state.character_descriptions:
        desc = state.character_descriptions[speaker]
        console.print(Panel.fit(f"[bold cyan]{speaker}[/]\n{desc}", title="角色信息", style="cyan"))
    
    # 显示剧情文本
    typewriter_effect(current.get("text", ""))
    
    # 显示选择项
    if "choices" in current and current["choices"]:
        choices = list(current["choices"].items())
        display_choices(choices)

def handle_input(state):
    """处理用户输入"""
    current = state.data.get(state.current_node, {})
    choices = list(current.get("choices", {}).items())
    
    while True:
        try:
            user_input = console.input("[bold cyan]请输入选项编号 (Q退出) > [/bold cyan]").strip()
            
            if user_input.upper() == "Q":
                console.print("[bold red]游戏已退出[/bold red]")
                exit()
            
            choice_idx = int(user_input) - 1
            if 0 <= choice_idx < len(choices):
                selected_key = choices[choice_idx]
                state.current_node = current["choices"][selected_key]
                return
            console.print("[bold red]无效的选项编号，请重新输入[/bold red]")
        except ValueError:
            console.print("[bold red]请输入有效的数字编号[/bold red]")

def load_data(state):
    """加载游戏数据"""
    try:
        with open("data.json", "r", encoding="utf-8") as f:
            state.data = json.load(f)
            state.player_name = state.data["player"]["name"]
            state.character_descriptions = {
                char: details["description"] 
                for char, details in state.data["characters"].items()
            }
            state.current_node = state.data.get("start_node", "intro")
    except FileNotFoundError:
        console.print("[bold red]错误：找不到data.json文件[/bold red]")
        exit(1)

def save_progress(state):
    """保存游戏进度"""
    with open("save.json", "w") as f:
        json.dump({"current_node": state.current_node}, f, indent=2)

def load_progress(state):
    """加载游戏进度"""
    try:
        with open("save.json", "r") as f:
            progress = json.load(f)
            state.current_node = progress["current_node"]
            return True
    except (FileNotFoundError, json.JSONDecodeError):
        return False

def show_title():
    """显示游戏标题"""
    console.clear()
    console.print(Panel.fit("[bold yellow]文字冒险游戏[/]", 
                          subtitle="按任意键开始", 
                          style="bold magenta"))

def main():
    """主游戏循环"""
    state = GameState()
    load_data(state)
    
    show_title()
    console.input()
    
    # 进度加载
    if load_progress(state):
        resp = console.input("[bold yellow]检测到存档，是否继续？(Y/N)[/] ").upper()
        if resp != "Y":
            state.current_node = state.data.get("start_node", "intro")
    
    while True:
        clear_screen()
        try:
            display_text(state)
            
            # 检查结束条件
            current = state.data[state.current_node]
            if not current.get("choices"):
                console.print(Panel("[bold red]游戏结束 - 感谢游玩！[/]", 
                                  style="bold red"))
                save_progress(state)
                break
                
            handle_input(state)
            save_progress(state)
            
        except KeyError as e:
            console.print(f"[bold red]游戏数据错误：缺失节点 {e}[/]")
            break

if __name__ == "__main__":
    main()